package com.fasteat.menu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasteat.common.entity.GlobalException;
import com.fasteat.common.entity.StatusCode;
import com.fasteat.menu.async.ReportAsync;
import com.fasteat.menu.entity.ReportMessage;
import com.fasteat.menu.entity.ReportType;
import com.fasteat.menu.entity.vo.DisposeReportVo;
import com.fasteat.menu.entity.vo.ReportSearchMap;
import com.fasteat.menu.entity.vo.SimpleMenuVo;
import com.fasteat.menu.mapper.MenuMapper;
import com.fasteat.menu.mapper.ReportMessageMapper;
import com.fasteat.menu.mapper.ReportTypeMapper;
import com.fasteat.menu.service.ReportService;
import com.fasteat.menu.util.NumberUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author run
 * @since 2021-01-19
 */
@Service
public class ReportServiceImpl extends ServiceImpl<ReportTypeMapper, ReportType> implements ReportService {


    @Autowired
    private ReportTypeMapper typeMapper;

    @Autowired
    private ReportMessageMapper messageMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private ReportAsync reportAsync;

    @Override
    public boolean createReportMessage(ReportMessage reportMessage) {
        //TODO 等待权限模块获取用户id
        String userId = reportMessage.getReporterId();

        //判断是否本人填写的举报信息
        boolean flag = userId.equals(reportMessage.getReporterId());
        if (!flag) {
            throw new GlobalException(StatusCode.ERROR,"非本人操作");
        }
        if (menuMapper.selectById(reportMessage.getMenuId()) == null){
            throw new GlobalException(StatusCode.ERROR,"无法举报不存在的菜谱");
        }
        //id置空 等待mybatis-plus填充
        reportMessage.setId(null);
        return messageMapper.insert(reportMessage) > 0;
    }

    @Override
    public boolean createReportType(ReportType reportType) {

        Map<String,Object> map = new HashMap<>(1,1);
        map.put("report_name",reportType.getReportName());

        List<ReportType> reportTypeByName = typeMapper.selectByMap(map);
        //如果该举报类别名称已存在
        if (!reportTypeByName.isEmpty()){
            throw new GlobalException(StatusCode.DUPLICATE,"该举报类别名称已存在");
        }
        //id置空 等待mybatis-plus填充
        reportType.setId(null);
        return typeMapper.insert(reportType) > 0;
    }

    @Override
    public boolean updateReportMessage(ReportMessage reportMessage) {
        return messageMapper.updateById(reportMessage) > 0;
    }

    @Override
    public boolean updateReportType(ReportType reportType) {

        Map<String,Object> map = new HashMap<>(1,1);
        map.put("report_name",reportType.getReportName());

        List<ReportType> reportTypeByName = typeMapper.selectByMap(map);

        //如果该举报类别名称已存在,且id不同
        if (!reportTypeByName.isEmpty() && reportTypeByName.get(0).getId().equals(reportType.getId())){
            throw new GlobalException(StatusCode.DUPLICATE,"该举报类别名称已存在，无法修改");
        }
        return typeMapper.updateById(reportType) > 0;
    }

    @Override
    public boolean deleteReportMessage(String reportMessageId,boolean isAdmin) {
        return messageMapper.deleteById(reportMessageId) > 0;
    }

    @Override
    public boolean deleteReportType(String reportTypeId) {
        return typeMapper.deleteById(reportTypeId) > 0;
    }

    @Override
    public List<ReportType> searchReportType() {
        return typeMapper.selectList(null);
    }

    @Override
    public IPage<ReportMessage> searchReportMessage(ReportSearchMap searchMap, Integer page, Integer size, boolean isAdmin) {
        Page<ReportMessage> reportMessagePage = new Page<>(page,size);
        QueryWrapper<ReportMessage> wrapper = new QueryWrapper<>();

        selectConditionBuild(wrapper,searchMap);

        if (!isAdmin){
            //TODO 等待权限模块获取用户id
            wrapper.eq("reporter_id","id");
        }

        return setMenuTitle(messageMapper.selectPage(reportMessagePage,wrapper));
    }

    @Override
    public List<ReportMessage> searchReportMessage(ReportSearchMap searchMap, boolean isAdmin) {
        QueryWrapper<ReportMessage> wrapper = new QueryWrapper<>();

        selectConditionBuild(wrapper,searchMap);

        if (!isAdmin){
            //TODO 等待权限模块获取用户id
            wrapper.eq("reporter_id","id");
        }

        return setMenuTitle(messageMapper.selectList(wrapper));
    }

    @Override
    @Transactional
    public boolean disposeReport(DisposeReportVo disposeReportVo) {
        ReportMessage reportMessage = messageMapper.selectById(disposeReportVo.getReportMessageId());
        if (reportMessage == null){
            throw new GlobalException(StatusCode.ERROR,"该举报信息不存在，无法处理");
        }

        if (reportMessage.getIsDispose().equals(1)){
            throw new GlobalException(StatusCode.ERROR,"该举报信息无法重复处理");
        }

        UpdateWrapper<ReportMessage> wrapper = new UpdateWrapper<>();
        wrapper.eq("id",disposeReportVo.getReportMessageId())
                .set("is_dispose",1);

        int result = messageMapper.update(new ReportMessage(), wrapper);

        if (disposeReportVo.getAction() != null && disposeReportVo.getAction().equals(1)){
            int retVal = menuMapper.deleteById(reportMessage.getMenuId());
            if (retVal == 0){
                throw new GlobalException(StatusCode.ERROR,"删除菜谱失败，请重试");
            }
        }

        if (result > 0){
            reportAsync.pushMessage(reportMessage, disposeReportVo.getAction());
        }

        return result > 0;
    }

    //筛选条件封装
    public void selectConditionBuild(QueryWrapper<ReportMessage> wrapper,ReportSearchMap searchMap){
        if (searchMap == null) {
            return;
        }

        String keyword = searchMap.getKeyword();
        Integer status = searchMap.getDisposeStatus();
        Integer timeSort = searchMap.getTimeSort();
        List<String> reportType = searchMap.getReportType();

        wrapper.eq(NumberUtil.isInRange(status,0,1),"is_dispose", status);

        wrapper.in(reportType != null,"report_id",reportType);

        wrapper.orderBy(NumberUtil.isInRange(timeSort,0,1), timeSort == 1,"gmt_create");

        keyword = keyword == null ? null : keyword.trim();

        final String finalKeyword = keyword;

        boolean flag = StringUtils.isNotEmpty(finalKeyword);

        wrapper.and(flag, QueryWrapper ->
                QueryWrapper.in(flag,"menu_id",messageMapper.getMenuIdOfKeyword('%' + finalKeyword + '%'))
                            .or().like(flag,"report_description",finalKeyword));

    }

    private List<ReportMessage> setMenuTitle(List<ReportMessage> reportMessages){
        if (reportMessages.isEmpty()){
            return reportMessages;
        }
        List<String> menuIds = reportMessages.stream().map(ReportMessage :: getMenuId).collect(Collectors.toList());
        List<SimpleMenuVo> menuVos = menuMapper.getSimpleMenuVosOfIds(menuIds);
        Map<String, String> collect = menuVos.stream()
                                        .collect(Collectors.toMap(SimpleMenuVo::getMenuId, SimpleMenuVo::getMenuTitle));

        //将菜谱标题封装进举报信息内
        reportMessages.forEach(reportMessage ->
            reportMessage.setMenuTitle(collect.getOrDefault(reportMessage.getMenuId(),"该菜谱状态异常"))
        );
        return reportMessages;
    }

    private IPage<ReportMessage> setMenuTitle(IPage<ReportMessage> reportMessages){
        setMenuTitle(reportMessages.getRecords());
        return reportMessages;
    }
}
